package quicklunch.e2.goodies.utils;

//import static quicklunch.e1.goodies.utils.ClassUtils.instanceOf;
import static quicklunch.e2.goodies.utils.ObjectUtils.eq;
import static quicklunch.e2.goodies.utils.StringUtils.hasLength; //import static quicklunch.e1.goodies.utils.StringUtils.mathches;

import java.awt.Component;
import java.awt.Container;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;

import javax.swing.JCheckBox;
import javax.swing.JFormattedTextField;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.JTextPane;

public abstract class UIComponentUtils {

    public static Component findComponent(String nameOrregex,
            Container container, boolean usingRegex) {
        Component[] components = getAllComponentsIfNamePrepared(container);
        Component returnComponent = null;

        if (usingRegex) {
            Pattern pattern = Pattern.compile(nameOrregex);
            for (Component component : components) {
                if (component.getName() != null
                        && pattern.matcher(component.getName()).matches()) {
                    returnComponent = component;
                    break;
                }
            }
            return returnComponent;
        }

        for (Component component : components) {
            if (eq(component.getName(), nameOrregex)) {
                returnComponent = component;
                break;
            }
        }
        return returnComponent;
    }

    public static Component[] findComponents(String regex, Container container) {
        Component[] components = getAllComponentsIfNamePrepared(container);
        List<Component> list = new ArrayList<Component>();
        Pattern pattern = Pattern.compile(regex);
        for (Component component : components) {
            if (component.getName() != null
                    && pattern.matcher(component.getName()).matches()) {
                list.add(component);
            }
        }

        return list.toArray(new Component[list.size()]);
    }

//    public static Container findContainer(String regex, Container container) {
//        Component[] components = getAllComponentsIfNamePrepared(container);
//
//        for (Component component : components) {
//
//            if (component instanceof Container
//                    && mathches(regex, component.getName()))
//                return (Container) component;
//        }
//        return null;
//    }

    public static Component[] getAllComponents(Container container) {
        ArrayList<Component> arrayList = new ArrayList<Component>();

        Component[] components = container.getComponents();

        for (int i = 0; i < components.length; i++) {
            if (components[i] instanceof Container) {
                List<Component> list = Arrays
                        .asList(getAllComponents((Container) components[i]));

                if (!list.isEmpty()) {
                    arrayList.addAll(list);
                }
            }
            arrayList.add(components[i]);
        }

        Object[] objects = arrayList.toArray();
        int size = objects.length;
        Component[] returnComponents = new Component[size];
        System.arraycopy(objects, 0, returnComponents, 0, size);
        return returnComponents;
    }

    public static Component[] getAllComponents(Container container,
            Class<?>[] classes) {
        ArrayList<Component> arrayList = new ArrayList<Component>();

        Component[] components = container.getComponents();

        for (int i = 0; i < components.length; i++) {
            if (components[i] instanceof Container) {
                List<Component> list = Arrays.asList(getAllComponents(
                        (Container) components[i], classes));

                if (!list.isEmpty()) {
                    arrayList.addAll(list);
                }
            }

            for (Class<?> class1 : classes) {
             if(class1.isInstance(components[i])){
                //if (instanceOf(class1, components[i])) {
                    arrayList.add(components[i]);
                    break;
                }
            }

        }

        Object[] objects = arrayList.toArray();
        int size = objects.length;
        Component[] returnComponents = new Component[size];
        System.arraycopy(objects, 0, returnComponents, 0, size);
        return returnComponents;
    }

    public static Component[] getAllComponentsIfNamePrepared(Container container) {
        List<Component> arrayList = new ArrayList<Component>();

        Component[] components = container.getComponents();
        for (Component component : components) {

            if (component instanceof Container) {
                // System.out.println(component);
                List<Component> list = Arrays
                        .asList(getAllComponentsIfNamePrepared((Container) component));

                if (!list.isEmpty()) {
                    arrayList.addAll(list);
                }

            }

            if (hasLength(component.getName()))
                arrayList.add(component);

        }

        Object[] objects = arrayList.toArray();
        int size = objects.length;
        Component[] returnComponents = new Component[size];
        System.arraycopy(objects, 0, returnComponents, 0, size);
        return returnComponents;
    }

    public static Component[] getAllComponentsIfNamePrepared(JMenu menu) {
        List<Component> arrayList = new ArrayList<Component>();

        Component[] components = menu.getMenuComponents();
        for (Component component : components) {
            if (component instanceof JMenu) {
            }

            if (component instanceof JMenu) {
                // System.out.println(component);
                List<Component> list = Arrays
                        .asList(getAllComponentsIfNamePrepared((JMenu) component));

                if (!list.isEmpty()) {
                    arrayList.addAll(list);
                }

            }

            if (hasLength(component.getName()))
                arrayList.add(component);

        }

        Object[] objects = arrayList.toArray();
        int size = objects.length;
        Component[] returnComponents = new Component[size];
        System.arraycopy(objects, 0, returnComponents, 0, size);
        return returnComponents;
    }

    public static Component[] getAllComponentsIfNamePrepared(JMenuBar menuBar) {
        List<Component> arrayList = new ArrayList<Component>();

        Component[] components = menuBar.getComponents();
        for (Component component : components) {

            if (component instanceof JMenu) {
                // System.out.println(component);
                List<Component> list = Arrays
                        .asList(getAllComponentsIfNamePrepared((JMenu) component));

                if (!list.isEmpty()) {
                    arrayList.addAll(list);
                }
                if (hasLength(component.getName()))
                    arrayList.add(component);
                continue;
            }

            if (component instanceof Container) {
                // System.out.println(component);
                List<Component> list = Arrays
                        .asList(getAllComponentsIfNamePrepared((Container) component));

                if (!list.isEmpty()) {
                    arrayList.addAll(list);
                }
                if (hasLength(component.getName()))
                    arrayList.add(component);
                continue;
            }

        }

        Object[] objects = arrayList.toArray();
        int size = objects.length;
        Component[] returnComponents = new Component[size];
        System.arraycopy(objects, 0, returnComponents, 0, size);
        return returnComponents;
    }

    public static String getText(Component component) {
        if (component instanceof JTextArea) {
            JTextArea textArea = (JTextArea) component;
            return textArea.getText();
        } else if (component instanceof JLabel) {
            JLabel label = (JLabel) component;
            return label.getText();
        } else if (component instanceof JFormattedTextField) {
            JFormattedTextField formattedTextField = (JFormattedTextField) component;
            return formattedTextField.getText();
        } else if (component instanceof JTextField) {
            JTextField textField = (JTextField) component;
            return textField.getText();
        } else if (component instanceof JCheckBox) {
            JCheckBox checkBox = (JCheckBox) component;
            return checkBox.getText();
        } else if (component instanceof JTextPane) {
            JTextPane textPane = (JTextPane) component;
            return textPane.getText();
        }

        return component.toString();
    }

    public static Map<String, Component> toMap(Component[] components) {
        Map<String, Component> map = new HashMap<String, Component>();
        for (Component component : components) {
            map.put(component.getName(), component);
        }
        return map;
    }

    public static CashedComponentMap createCashedComponentMap(
            Container container) {
        return new CashedComponentMap(
                toMap(getAllComponentsIfNamePrepared(container)));
    }

    public static class CashedComponentMap implements Map<String, Component> {
        Map<String, Component> map;

        private CashedComponentMap() {
            this.map = new HashMap<String, Component>();
        }

        private CashedComponentMap(Map<String, Component> map) {
            this.map = map;
        }

        public void clear() {
            this.map.clear();
        }

        public boolean containsKey(Object key) {
            return this.map.containsKey(key);
        }

        public boolean containsValue(Object value) {
            return this.map.containsValue(value);
        }

        public Set<java.util.Map.Entry<String, Component>> entrySet() {
            return this.map.entrySet();
        }

        public Component get(Object key) {
            return this.map.get(key);
        }

        public boolean isEmpty() {
            return this.map.isEmpty();
        }

        public Set<String> keySet() {
            return this.map.keySet();
        }

        public Component put(String key, Component value) {
            return this.map.put(key, value);
        }

        public void putAll(Map<? extends String, ? extends Component> t) {
            this.map.putAll(t);
        }

        public Component remove(Object key) {
            return this.map.remove(key);
        }

        public int size() {
            return this.map.size();
        }

        public Collection<Component> values() {
            return this.map.values();
        }

        public CashedComponentMap getMap(Class<?>[] classes) {

            Collection<Component> collection = values();
            CashedComponentMap map = new CashedComponentMap();
            for (Component component : collection) {
                for (Class<?> class1 : classes) {
                    if (class1.isInstance(component)) {
                        map.put(component.getName(), component);
                        break;
                    }
                }
            }

            return map;
        }
    }

}
